﻿using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using MiPadAndroid.Models;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Client.Subscribing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;

namespace MiPadAndroid.Services
{
    public class MqttService
    {
        public IMqttClient mqttClient = null;
        public string host { get; set; }
        int port = 1883;

        public byte ConnectionState { get; set; } = 0;

        public event EventHandler<EventArgs> OnConnected;
        public event EventHandler<EventArgs> OnDisconnected;
        public event EventHandler<EventArgs> OnMessage;

        public MqttService(string host)
        {
            this.host = host;
        }

        async public void Connect()
        {
            ConnectionState = 1;
            // 连接MQTT服务
            string clientId = Guid.NewGuid().ToString();
            var options = new MqttClientOptionsBuilder()
                .WithClientId(clientId)
                .WithCleanSession(true)
                .WithWillDelayInterval(5)
                .WithTcpServer(host, port);
            var factory = new MqttFactory();
            var mqttClient = factory.CreateMqttClient();
            mqttClient.UseConnectedHandler((action) =>
            {
                ConnectionState = 2;
                OnConnected(this, new EventArgs());
            });
            mqttClient.UseDisconnectedHandler((action) =>
            {
                ConnectionState = 0;
                OnDisconnected(this, new EventArgs());
            });
            mqttClient.UseApplicationMessageReceivedHandler(e =>
            {
                OnMessage(e.ApplicationMessage, new EventArgs());
            });
            this.mqttClient = mqttClient;
            await mqttClient.ConnectAsync(options.Build(), CancellationToken.None);
        }

        // 发布
        public void Publish(string topic, PayloadMessage payload)
        {
            if (ConnectionState == 2)
            {
                MqttApplicationMessage mqttApplicationMessage = new MqttApplicationMessage();
                mqttApplicationMessage.Topic = topic;
                mqttApplicationMessage.Payload = System.Text.UTF8Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(payload));
                mqttClient.PublishAsync(mqttApplicationMessage);
            }
            else if (ConnectionState == 0)
            {
                this.Connect();
            }
        }

        public void Subscribe(string topic)
        {
            mqttClient.SubscribeAsync(topic);
        }


        public static string GetIP()
        {
            string ip = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()
                .Select(p => p.GetIPProperties())
                .SelectMany(p => p.UnicastAddresses)
                .Where(p => p.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !System.Net.IPAddress.IsLoopback(p.Address))
                .FirstOrDefault()?.Address.ToString();
            return ip;
        }

        public static bool TcpClientCheck(string ip, int port = 1883)
        {
            IPAddress ipa = IPAddress.Parse(ip);
            IPEndPoint point = new IPEndPoint(ipa, port);
            TcpClient tcp = null;
            try
            {
                tcp = new TcpClient();
                tcp.Connect(point);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
            finally
            {
                if (tcp != null)
                {
                    tcp.Close();
                }
            }
        }
    }
}